package cn.lg.soar.common.util;

import cn.lg.soar.common.util.data.DataUtil;
import org.springframework.util.FileCopyUtils;
import org.springframework.util.ResourceUtils;

import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.text.MessageFormat;

/**
 * @author luguoxiang
 * 开源项目：https://gitee.com/lgx1992/lg-soar 求star！请给我star！请帮我点个star！
 */
public interface FileUtil {

    String PNG_BASE64_HEAD = "data:image/png;base64,";
    String JPEG_BASE64_HEAD = "data:image/jpeg;base64,";
    String GIF_BASE64_HEAD = "data:image/gif;base64,";

    /**
     * 将图片数据转为base64
     * @param bufferedImage 图片缓冲
     * @param imgType 图片类型
     * @return 图片base64数据
     * @author luguoxiang
     */
    static String bufferedImageToBase64(BufferedImage bufferedImage, String imgType){
        byte[] bytes;
        // 生成字节流
        try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
            ImageIO.write(bufferedImage, imgType, baos);
            bytes = baos.toByteArray();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        // 生成base64数据
        String base64 = DataUtil.byteToBase64(bytes)
                .trim()
                .replaceAll("\n", "")
                .replaceAll("\r", "");
        // 生成图片 base64 数据
        return MessageFormat.format("data:image/{0};base64,{1}", imgType, base64);
    }

    /**
     * 将图片数据转为base64
     * @param bufferedImage 图片缓冲
     * @return 图片base64数据
     * @author luguoxiang
     */
    static String bufferedImageToBase64(BufferedImage bufferedImage){
        return FileUtil.bufferedImageToBase64(bufferedImage, "jpeg");
    }


    /**
     * HttpServletResponse 输出图片
     * @param bufferedImage 图片缓冲
     * @param resp 请求响应
     * @param imgType 图片类型
     * @throws IOException
     */
    static void bufferedImageToOut(BufferedImage bufferedImage, HttpServletResponse resp, String imgType) throws IOException {
        resp.setContentType("image/"+ imgType +";charset=utf-8");
        try (ServletOutputStream outputStream = resp.getOutputStream()){
            ImageIO.write(bufferedImage, imgType, outputStream);
        }
    }

    /**
     * HttpServletResponse 输出图片
     * @param bufferedImage 图片缓冲
     * @param resp 请求响应
     * @throws IOException
     */
    static void bufferedImageToOut(BufferedImage bufferedImage, HttpServletResponse resp) throws IOException {
        FileUtil.bufferedImageToOut(bufferedImage, resp, "jpeg");
    }

    /**
     * 响应前端下载服务器文件
     * @param path 文件路径
     * @param filename 下载后的文件名
     * @param req 请求
     * @param resp 响应
     */
    static void webDownload( File file, String filename, HttpServletRequest req, HttpServletResponse resp) {
        if(!file.exists()) {
            return;
        }
        //判断文件类型
        String mimeType = URLConnection.guessContentTypeFromName(file.getName());
        if(mimeType == null) {
            mimeType = "application/octet-stream";
        }
        if(null == filename){
            filename = file.getName();
        }
        String agent = req.getHeader("User-Agent");
        // 根据不同的客户端进行不同的编码
        try {
            if (agent.contains("MSIE")) {
                filename = URLEncoder.encode(filename, "utf-8");
            } else if (agent.contains("Firefox")) {
                filename = "=?utf-8?B?" + DataUtil.byteToBase64(filename.getBytes(StandardCharsets.UTF_8)) + "?=";
            } else {
                filename = URLEncoder.encode(filename, "utf-8");
            }
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
        //设置Content-Disposition响应头，一方面可以指定下载的文件名，另一方面可以引导浏览器弹出文件下载窗口
        resp.setHeader("Content-Disposition", "attachment;fileName=\"" + filename + "\"");
        resp.setContentType(mimeType);
        resp.setContentLengthLong(file.length());

        // 文件下载
        try (FileInputStream fileInputStream = new FileInputStream(file);
             BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream);
             ServletOutputStream outputStream = resp.getOutputStream()
        ){
            FileCopyUtils.copy(bufferedInputStream, outputStream);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    static void webDownload(String path, String name, HttpServletRequest req, HttpServletResponse resp) {
        webDownload(new File(path), name, req, resp);
    }

    /**
     * 响应前端下载服务器文件
     * @param path 文件路径
     * @param req 请求
     * @param resp 响应
     */
    static void webDownload(String path, HttpServletRequest req, HttpServletResponse resp) {
        webDownload(path, null, req, resp);
    }

    /**
     * 读取文本方法
     * @param fileUrl 文件路径
     * @param charset 编码方式
     * @return
     */
    static String readString(String fileUrl, String charset){
        File file = null;
        try {
            file = ResourceUtils.getFile(fileUrl);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        return FileUtil.readString(file, charset);
    }

    /**
     * 读取文本方法
     * @param file 文件
     * @param charset 编码方式
     * @return
     */
    static String readString(File file, String charset) {
        StringBuilder sb = new StringBuilder();
        try (FileInputStream fileInputStream = new FileInputStream(file);
                InputStreamReader isr = new InputStreamReader(fileInputStream, charset);
             BufferedReader br = new BufferedReader(isr)) {
            String lineTxt;
            while ((lineTxt = br.readLine()) != null) {
                sb.append(new String(lineTxt.getBytes(), charset));
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return sb.toString();
    }

    /**
     * 读取文本方法
     * @param fileUrl 文件路径
     * @return
     */
    static String readString(String fileUrl){
        return FileUtil.readString(fileUrl, "utf-8");
    }

    /**
     * 读取文本方法
     * @param file 文件
     * @return
     */
    static String readString(File file){
        return FileUtil.readString(file, "utf-8");
    }

    static byte[] readBytes(InputStream input) {
        ByteArrayOutputStream output = new ByteArrayOutputStream();
        try {
            byte[] buffer = new byte[1024*4];
            int n = 0;
            while (-1 != (n = input.read(buffer))) {
                output.write(buffer, 0, n);
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return output.toByteArray();
    }

    /**
     * 获取文件扩展名
     * @param filePath 文件路径或文件名
     * @return
     */
    static String getSuffix(String filePath) {
        return filePath.substring(filePath.lastIndexOf(".") + 1);
    }

    /**
     * 生成文件唯一标识码
     * @param digest 文件信息摘要
     * @param size 文件大小
     * @return
     */
    static String toCode(String digest, Long size) {
        return MessageFormat.format("{0}_{1}", digest, size.toString());
    }

    /**
     * 删除所有文件和目录
     * @param file
     */
    static void deleteDirectory(File file) {
        if (file.isDirectory()) {
            File[] files = file.listFiles();
            if (files != null && files.length != 0) {
                for (File x: files) {
                    // 递归删除子目录
                    deleteDirectory(x);
                }
            }
        }
        // 删除文件或空目录
        file.delete();
    }


    /**
     * 删除所有文件
     * @param file
     */
    static void deleteFile(File file) {
        if (file.isDirectory()) {
            File[] files = file.listFiles();
            if (files != null && files.length != 0) {
                for (File x: files) {
                    // 递归删除子目录
                    deleteFile(x);
                }
            }
            return;
        }
        // 删除文件
        file.delete();
    }

}
